package com.yyge.util;

import com.alibaba.fastjson2.JSONObject;
import com.yyge.entity.BaseEntity;
import com.yyge.vo.R;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ServletUtil {
    /**
     * 从request请求中获取url参数，并将参数的值封装为一个map对象
     * @param req
     * @return
     */
    public static JSONObject parameter2jsonObject(HttpServletRequest req) {
        // 获取所有的url参数的名字
        Enumeration<String> parameterNames = req.getParameterNames();
        // 将所有url参数和值以键值对的形式保存到map集合
        JSONObject jsonObject = new JSONObject();
        // 约定： 对象t中的属性必须和url参数parameter相同
        while (parameterNames.hasMoreElements()) {
            // 得到一个具体的url参数
            String parameter = parameterNames.nextElement();
            // 根据url参数获取值
            String value = req.getParameter(parameter);

            if (value.trim().length() > 0) {
                jsonObject.put(parameter, value);
            }
        }
        return jsonObject;
    }

    /**
     * 从request请求中获取url参数，将参数转换为类型为tClass的java对象
     * @param req
     * @param tClass
     * @param <T>
     * @return
     */
    public static <T> T parameter2dto(HttpServletRequest req,Class<T> tClass){
        JSONObject jsonObject = parameter2jsonObject(req);
        return jsonObject.to(tClass);
    }

    /**
     * 从request请求体中提取用户提交的json数据
     * 前后端分离，使用json字符串来传输数据
     * @param req httpServletRequest请求对象
     * @param tClass 要将post请求中的json转换为对应的java类型
     * @return tClass的实例
     * @throws IOException
     */
    public static BaseEntity fetchDataFromRequest(HttpServletRequest req,Class<? extends BaseEntity> tClass) throws IOException {
        try(// 字节输入流
            ServletInputStream inputStream = req.getInputStream();
            // 将字节输入流转换为UTF-8编码的字符输入流 r
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            // 将字符输入流转换为带有缓存的字符输入流
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader)){
            // 接收用户输入的数据
            StringBuilder builder = new StringBuilder();
            String line;

            // 每次读一行
            while ((line = bufferedReader.readLine()) != null) {
                // 将读取到的行拼接到builder
                builder.append(line);
            }

            // 提起读取到的数据
            String json = builder.toString();
            // 将json转换为map
            JSONObject jsonObject = JSONObject.parse(json);
            // 得到tClass类所有的属性
            Field[] declaredFields = tClass.getDeclaredFields();

            // 获取tClass属性名的集合
            List<String> properties = Arrays.stream(declaredFields)
                    .map(field -> field.getName())
                    .collect(Collectors.toList());


            BaseEntity baseEntity = tClass.newInstance();
            // 保存没有在tClass中声明的属性
            Map<String, Object> params = baseEntity.getParams();


            // 遍历客户端传递的对象
            jsonObject.forEach((key,value) -> {
                if (properties.contains(key)) {
                    try {
                        BeanUtils.setProperty(baseEntity, key, value);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                } else {
                    params.put(key, value);
                }
            });

            // return JSONObject.parseObject(json,tClass);
            return baseEntity;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String,Object> fetchDataFromRequest(HttpServletRequest req) throws IOException {
        try(// 字节输入流
            ServletInputStream inputStream = req.getInputStream();
            // 将字节输入流转换为UTF-8编码的字符输入流
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            // 将字符输入流转换为带有缓存的字符输入流
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader)){
            // 接收用户输入的数据
            StringBuilder builder = new StringBuilder();
            String line;

            // 每次读一行
            while ((line = bufferedReader.readLine()) != null) {
                // 将读取到的行拼接到builder
                builder.append(line);
            }

            // 提起读取到的数据
            String json = builder.toString();
            // 通过fastjson，将json字符串转换为Map集合
            return JSONObject.parseObject(json);
        }
    }


    /**
     * 将result对象转换为json后输出到客户端
     * @param resp
     * @param result
     * @throws IOException
     */
    public static void writeResult2Client(HttpServletResponse resp, R result) throws IOException {
        // 将查询结果转换为json
        String jsonString = JSONObject.toJSONString(result);

        // 将json输出客户端
        try (PrintWriter writer = resp.getWriter()) {
            writer.write(jsonString);
            writer.flush();
        }
    }
}